/**************************************************************************************
*  Flash.c
*
*  This file implements all native methods declared in the Flash class.
*  IMPORTANT:
*    This file contains only basic commands for programming AMD flash
*    chip Am29F010. If your system uses different flash memory or you
*    require additional functionality you will need to modify code
*    contained in this file.
*
*
* NOTE:
*  Be careful when accessing the native methods arguments. If native method is
*  declared as static then the first argoment starts at index zero. Non-static native
*  methods have arguments starting at index one, while argument at index zero is
*  a reference to the object on which the method is being invoked.
**************************************************************************************
*
* This file is covered by the GNU GPL with the following exception:
*   As a special exception, the copyright holders of this library give you permission
*   to link this library with independent modules to produce an executable, regardless
*   of the license terms of these independent modules, and to copy and distribute the
*   resulting executable under terms of your choice, provided that you also meet, for
*   each linked independent module, the terms and conditions of the license of that
*   module. An independent module is a module which is not derived from or based on
*   this library. If you modify this library, you may extend this exception to your
*   version of the library, but you are not obligated to do so. If you do not wish
*   to do so, delete this exception statement from your version.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY,  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL RTJ COMPUTING BE LIABLE FOR ANY CLAIM, DAMAGES
* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Copyright (c) 2000-2002 RTJ Computing Pty. Ltd. All rights reserved.
**************************************************************************************/

#include "javavm.h"

extern vm_config_t vmconfig;

#define FLASH_BASE      ((uint8 *)0x20000)
#define FLASH_SIZE      0x20000

/*
** Flash memory sector offsets. This table is provided as some flash chips
** may have sectors of diffrents sizes (ie. Am29F100B/T).
*/
static const uint32 sectors[] =
{
    0x00000;
    0x04000;
    0x08000;
    0x0C000;
    0x10000;
    0x14000;
    0x18000;
    0x1C000;
};
#define SECTOR_COUNT    (sizeof(sectors) / sizeof(sector[0]))

static bool writeByte(int32 address, uint8 value);
static bool flashPoll(int32 address, uint8 value);

/****************************************************************************
* Verifies if the requested flash memory area is valid. We have to make sure
* that the base address of the memory region equals the flash memory physical
* address.
*
* Java prototype:
*       protected static native boolean regionOk0(int start, int length);
*
****************************************************************************/
int16 javax_memory_Flash_regionOk0(int32 param[], int32 *retval)
{
    *retval = true;
    if ((uint8 *)param[0] != FLASH_BASE || (uint8 *)(param[0] + param[1]) > (FLASH_BASE + FLASH_SIZE))
        *retval = false;
    return NO_EXCEP;
}

/****************************************************************************
* Writes a byte into memory.
*
* Java prototype:
*       protected static native boolean writeByte0(int address, int value);
*
****************************************************************************/
int16 javax_memory_Flash_writeByte0(int32 param[], int32 *retval)
{
    *retval = writeByte(param[0], (uint8)param[1]);
    return NO_EXCEP;
}

/****************************************************************************
* Writes a short into memory MSB first.
*
* Java prototype:
*       protected static native boolean writeShort0(int address, int value);
*
****************************************************************************/
int16 javax_memory_Flash_writeShort0(int32 param[], int32 *retval)
{
    *retval = writeByte(param[0], (uint8)(param[1] >> 8));
    if (*retval)
        *retval = writeByte(param[0]+1, (uint8)param[1]);
    return NO_EXCEP;
}

/****************************************************************************
* Writes an int  into memory MSB first.
*
* Java prototype:
*       protected static native boolean writeInt0(int address, int value);
*
****************************************************************************/
int16 javax_memory_Flash_writeInt0(int32 param[], int32 *retval)
{
    *retval = writeByte(param[0], (uint8)(param[1] >> 24));
    if (*retval)
    {
        *retval = writeByte(param[0]+1, (uint8)(param[1] >> 16));
        if (*retval)
        {
            *retval = writeByte(param[0]+2, (uint8)(param[1] >> 8));
            if (*retval)
                *retval = writeByte(param[0]+3, (uint8)param[1]);
        }
    }
    return NO_EXCEP;
}

/****************************************************************************
* Writes a byte array into memory.
*
* Java prototype:
*       protected static native boolean writeBytes0(int address, byte[] src, int start, int length);
*
****************************************************************************/
int16 javax_memory_Flash_writeBytes0(int32 param[], int32 *retval)
{
    uint8 *arr;
    int16 i;

    arr = (uint8 *)vmconfig.vmGetArray(param[1]);
    if (arr != NULL)
    {
        *retval = true;
        for (i=0; i < param[3] && *retval; i++)
            *retval = writeByte(param[0]+i, arr[(int16)param[2] + i]);
    }
    return NO_EXCEP;
}

/****************************************************************************
* Erases a sector in flash memory.
*
* Java prototype:
*       public static native boolean eraseSector(int sectorNo);
*
****************************************************************************/
int16 javax_memory_Flash_eraseSector(int32 param[], int32 *retval)
{
    *retval = true;
    int32 sector;

    if (param[0] < 1 || param[0] > SECTOR_COUNT)
        *retval = false;
    else
    {
        sector = sectors[param[0]-1];
        *(FLASH_BASE + 0x5555) = 0xAA;
        *(FLASH_BASE + 0x2AAA) = 0x55;
        *(FLASH_BASE + 0x5555) = 0x80;
        *(FLASH_BASE + 0x5555) = 0xAA;
        *(FLASH_BASE + 0x2AAA) = 0x55;
        *(FLASH_BASE + sector) = 0x30;

        *retval = flashPoll(sector, 0xFF);
    }
    return NO_EXCEP;
}

/****************************************************************************
* Writes a byte into flash memory.
*
* Input:    address - destination address
*           value   - value that has to be programmed
* Output:   none
* Return:   true    if successfull, false if programming failed
****************************************************************************/
static bool writeByte(int32 address, uint8 value)
{
    *(FLASH_BASE + 0x5555) = 0xAA;
    *(FLASH_BASE + 0x2AAA) = 0x55;
    *(FLASH_BASE + 0x5555) = 0xA0;
    *(FLASH_BASE + address) = value;

    return flashPoll(address, value);
}

/****************************************************************************
* Waits for a flash chip to finish programming operation. Function polls
* the DQ7/DQ5 for flash chip readiness.
*
* Input:    address - destination address
*           value   - programmed value
* Output:   none
* Return:   true    if successfull, false if programming failed
****************************************************************************/
static bool flashPoll(uint32 address, uint8 value)
{
    uint8 data;

    value &= 0x80;
    while (true)
    {
        data = *address;
        if ((data & 0x80) == value)
            break;
        if (data & 0x20)
        {
            data = *address;
            if ((data & 0x80) == value)
                break;
            return false;
        }
    }

    return true;
}

